/*
 * Copyright © 2008 PCCW Solutions All right reserved.
 *
 */
package com.blues.framework.db;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.Arrays;

import org.apache.commons.dbutils.ResultSetHandler;
import org.apache.log4j.Logger;

/**
 * 数据库基本调用类 
 * 
 * @see ResultSetHandler
 */
public abstract class BaseCaller {
	protected Logger logger = Logger.getLogger(this.getClass());

	/**
	 * 数据库联接对象
	 */
	protected Connection dbConn = null;
	
	/**
	 * 构造函数
	 */
	public BaseCaller() {
		super();
	}

    /**
     * 构造函数
     * 
     * @param dbConn <code>Connection</code> 参数设置数据库调用所使用的连接对象
     */
    public BaseCaller(Connection dbConn) {
        super();
        setConnection(dbConn);
    }

    /**
     * 获取当前数据库连接对象
     * 
     * @return <code>Connection</code> 调用所使用的连接对象
     */
	public Connection getConnection() {
		return this.dbConn;
	}

	/**
     * 设置数据库连接对象
     * 
     * @param <code>Connection</code> 调用所使用的连接对象
     */
	public void setConnection(Connection dbConn) {
		this.dbConn = dbConn;
	}

	// ======================================================================

    /**
     * Executes the given SELECT SQL without any replacement parameters.
     * The <code>Connection</code> is retrieved from the
     * <code>DataSource</code> set in the constructor.
     * 
     * @param sql The SQL statement to execute.
     * @param rsh The handler used to create the result object from 
     * the <code>ResultSet</code>.
     * 
     * @return An object generated by the handler.
     * @throws SQLException if a database access error occurs
     */
    public Object query(String sql, ResultSetHandler rsh) throws SQLException {
        return this.query(sql, new Object[]{}, rsh);
    }

    /**
     * Executes the given SELECT SQL with a single replacement parameter.
     * The <code>Connection</code> is retrieved from the
     * <code>DataSource</code> set in the constructor.
     * 
     * @param sql The SQL statement to execute.
     * @param param The replacement parameter.
     * @param rsh The handler used to create the result object from 
     * the <code>ResultSet</code>.
     * 
     * @return An object generated by the handler.
     * @throws SQLException if a database access error occurs
     */
    public Object query(String sql, Object param, ResultSetHandler rsh)
        throws SQLException {

        return this.query(sql, new Object[] { param }, rsh);
    }

    /**
     * Executes the given SELECT SQL query and returns a result object.
     * The <code>Connection</code> is retrieved from the 
     * <code>DataSource</code> set in the constructor.
     * 
     * @param sql The SQL statement to execute.
     * @param params Initialize the PreparedStatement's IN parameters with 
     * this array.
     * 
     * @param rsh The handler used to create the result object from 
     * the <code>ResultSet</code>.
     * 
     * @return An object generated by the handler.
     * @throws SQLException if a database access error occurs
     */
    public Object query(String sql, Object[] params, ResultSetHandler rsh)
        throws SQLException {

		Connection conn = dbConn;

		return this.query(conn, sql, params, rsh);
    }

    /**
     * Execute an SQL SELECT query without any replacement parameters.  The
     * caller is responsible for closing the connection.
     * 
     * @param conn The connection to execute the query in.
     * @param sql The query to execute.
     * @param rsh The handler that converts the results into an object.
     * @return The object returned by the handler.
     * @throws SQLException if a database access error occurs
     */
    public Object query(Connection conn, String sql, ResultSetHandler rsh)
        throws SQLException {

        return this.query(conn, sql, new Object[]{}, rsh);
    }
    
    /**
     * Execute an SQL SELECT query with a single replacement parameter. The
     * caller is responsible for closing the connection.
     * 
     * @param conn The connection to execute the query in.
     * @param sql The query to execute.
     * @param param The replacement parameter.
     * @param rsh The handler that converts the results into an object.
     * @return The object returned by the handler.
     * @throws SQLException if a database access error occurs
     */
    public Object query(Connection conn, String sql, Object param,
            ResultSetHandler rsh) throws SQLException {

        return this.query(conn, sql, new Object[] { param }, rsh);
    }
    
    /**
     * Execute an SQL SELECT query with replacement parameters.  The
     * caller is responsible for closing the connection.
     * 
     * @param conn The connection to execute the query in.
     * @param sql The query to execute.
     * @param params The replacement parameters.
     * @param rsh The handler that converts the results into an object.
     * @return The object returned by the handler.
     * @throws SQLException if a database access error occurs
     */
    public abstract Object query(Connection conn, String sql, Object[] params,
            ResultSetHandler rsh) throws SQLException ;

    
    /**
     * Throws a new exception with a more informative error message.
     * 
     * @param cause The original exception that will be chained to the new 
     * exception when it's rethrown. 
     * 
     * @param sql The query that was executing when the exception happened.
     * 
     * @param params The query replacement parameters; <code>null</code> is a 
     * valid value to pass in.
     * 
     * @throws SQLException if a database access error occurs
     */
    protected void rethrow(SQLException cause, String sql, Object[] params)
        throws SQLException {
		logger.error("@->sql: " + sql);
		if (params == null) {
            logger.error("@->params: []");
        } else {
			logger.error("@->params: " + Arrays.asList(params));
        }
		logger.error(cause, cause);
        throw cause;
    }

}
